package com.qys.livesMall.anchor.controller.app;


import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.qys.livesMall.anchor.business.AnchorLivesBusiness;
import com.qys.livesMall.anchor.model.dto.lives.sys.CreatePullFlowDTO;
import com.qys.livesMall.anchor.model.vo.lives.LiveInfoVO;
import com.qys.livesMall.anchor.model.vo.lives.app.AnchorLivesRoomVO;
import com.qys.livesMall.anchor.model.vo.lives.app.LivesStreamUrlVO;
import com.qys.livesMall.anchor.model.vo.lives.app.SettlementDataVO;
import com.qys.livesMall.common.result.R;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.shop.modal.vo.task.app.child.SellTaskGoodsChild;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.Instant;
import java.util.List;
import java.util.Map;


@RestController
@Tag(name = "APP-主播直播")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RequestMapping("/app/anchor/lives")
public class AppAnchorLivesController {

    @Value("${txlive.cutoffCallback.key}")
    private String key;

    private final AnchorLivesBusiness anchorLivesBusiness;


    @GetMapping("/startLive/{sellTaskId}")
    @Operation(summary = "根据主播带货任务开播", parameters = {@Parameter(name = "sellTaskId", description = "主播带货任务id")})
    public R<AnchorLivesRoomVO> startLive(@PathVariable Long sellTaskId) {
        anchorLivesBusiness.startLive(sellTaskId);
        return R.ok();
    }


    @GetMapping("/closeLive")
    @Operation(summary = "关闭直播")
    public R<?> closeLive() {
        try {
            anchorLivesBusiness.closeLive(SecurityUtils.getUserId(), true, null);
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
        return R.ok();
    }

    @GetMapping("/settlementData/{livesSessionId}")
    @Operation(summary = "获取结算数据")
    public R<SettlementDataVO> settlementData(@PathVariable Long livesSessionId) {
        return R.ok(anchorLivesBusiness.settlementData(livesSessionId));
    }

    @PostMapping("/autoCloseLive")
    @Operation(summary = "关闭直播(腾讯云直播断流回调接口，推流客户端主动断流除外)")
    public void closeLive(@RequestBody String jsonString) {
        Long userId = this.verificationSignature(jsonString);
        if(null == userId){
            return;
        }
        anchorLivesBusiness.closeLive(userId, true, null);
    }

    @PostMapping("/autoCloseLiveByAutoLive")
    @Operation(summary = "关闭直播(拉流转推腾讯云回调)")
    public void autoCloseLiveByAutoLive(@RequestBody String jsonString) {
        JSONObject jsonObject = JSONObject.parseObject(jsonString);
        String event = (String) jsonObject.get("callback_event");
        String streamId = (String) jsonObject.get("stream_id");
        if(StringUtils.isNotEmpty(streamId) && "TaskExit".equalsIgnoreCase(event)){
            anchorLivesBusiness.closeLive(Long.valueOf(streamId), true, null);
        }
    }

    /**
     * 验签
     * @param jsonString 参数
     * @return 用户ID
     */
    private Long verificationSignature(String jsonString){
        JSONObject jsonObject = JSONObject.parseObject(jsonString);
        Integer eventType = (Integer)jsonObject.get("event_type");
        Integer height = (Integer)jsonObject.get("height");
        if(1802 == height){
            //离开垫片回调不处理
            return null;
        }
        Integer errCode = (Integer)jsonObject.get("errcode");
        String streamId = (String) jsonObject.get("stream_id");
        if(eventType == 1){
            return null;
        }
        if(eventType == 0){
            //推流不做处理、推流客户端主动断流不处理（主播暂离功能）,只记录断流时间
            anchorLivesBusiness.updateDepartureTime(streamId, false);
            return null;
        }
        Integer t = (Integer)jsonObject.get("t");
        String sign = (String) jsonObject.get("sign");
        if(t == null || StringUtils.isBlank(sign) || StringUtils.isBlank(streamId)){
            return null;
        }
        if(!StringUtils.equals(SecureUtil.md5(key + t),sign)){
            return null;
        }
        if (t < Instant.now().getEpochSecond()) {
            return null;
        }
        return Long.parseLong(streamId);
    }


    @GetMapping("/initLiveRoom")
    @Operation(summary = "初始化直播间")
    public R<?> initLiveRoom(){
        try {
            anchorLivesBusiness.initLiveRoom(SecurityUtils.getUserId());
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
        return R.ok();
    }

    @GetMapping("/getPushUrl/{taskId}")
    @Operation(summary = "获取推流地址")
    public R<String> getPushUrl(@PathVariable Long taskId) {
        String pushUrl;
        try {
            pushUrl = anchorLivesBusiness.getPushUrl(taskId);
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
        return R.ok(pushUrl);
    }

    @GetMapping("/getPushUrl")
    @Operation(summary = "获取推流地址（无任务）")
    public R<String> getPushUrlNoTask() {
        String pushUrl;
        try {
            pushUrl = anchorLivesBusiness.getPushUrlNoTask();
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
        return R.ok(pushUrl);
    }

    @GetMapping({"/getPullUrl/{userId}", "/getPullUrl/{userId}/{excludeUserId}"})
    @Operation(summary = "获取播放地址", description = "excludeUserId 需要排除的主播userId，用于随机刷直播间")
    public R<LivesStreamUrlVO> getPlayUrl(@PathVariable Long userId, @PathVariable(required = false) Long excludeUserId){
        return R.ok(anchorLivesBusiness.getPlayUrl(userId, excludeUserId));
    }


    @GetMapping("/getLiveRoomId/{userId}")
    @Operation(summary = "根据用户获取直播间编号和场次id")
    public R<LiveInfoVO> getLiveRoomId(@PathVariable String userId){
        return R.ok(anchorLivesBusiness.getLiveRoomInfo(userId));
    }

    @GetMapping("/getLiveRoomGoods/{roomNum}")
    @Operation(summary = "获取直播间商品", description = "支持传入livesSessionId查询")
    public R<List<SellTaskGoodsChild>> getLiveRoomGoods(@PathVariable String roomNum) {
        List<SellTaskGoodsChild> goodsChildList;
        try {
            goodsChildList = anchorLivesBusiness.getLiveRoomGoods(roomNum);
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
        return R.ok(goodsChildList);
    }

    @PostMapping("/showGoods/{goodsId}")
    @Operation(summary = "主播展示带货商品")
    public R<?> showGoods(@PathVariable Long goodsId) {
        Boolean result = anchorLivesBusiness.showGoods(goodsId);
        if(result){
            return R.ok();
        }
        return R.fail();
    }

    @PostMapping("/setWish/{goodsId}/{total}")
    @Operation(summary = "主播设置带货心愿")
    public R<?> setWish(@PathVariable Long goodsId, @PathVariable Integer total) {
        Boolean result = anchorLivesBusiness.setWish(goodsId, total);
        if(result){
            return R.ok();
        }
        return R.fail();
    }


    @PostMapping("/autoLive/{taskId}")
    @Operation(summary = "拉流转播")
    public R<?> autoLive(@PathVariable Long taskId, @RequestBody @Validated CreatePullFlowDTO dto){
        String txTaskId;
        try {
            txTaskId = anchorLivesBusiness.autoLive(taskId, dto, false);
            if(StringUtils.isNotEmpty(txTaskId)){
                return R.ok(taskId);
            }else {
                return R.fail();
            }
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }

    @GetMapping("/startAutoLive/{id}")
    @Operation(summary = "前端判断开启自动直播")
    public R<Boolean> startAutoLive(@PathVariable Long id){
        return R.ok(anchorLivesBusiness.startAutoLive(id));
    }

    @GetMapping("/checkLiveStatus")
    @Operation(summary = "判断主播是否中断直播")
    public R<Map<String, Long>> checkLiveStatus(){
        return R.ok(anchorLivesBusiness.checkLiveStatus(SecurityUtils.getUserId()));
    }

    @PostMapping("/pauseAndStartLive")
    @Operation(summary = "恢复直播")
    public R<?> pauseAndStartLive(){
        Long userId = SecurityUtils.getUserId();
        anchorLivesBusiness.repushFlow(String.valueOf(userId));
        return R.ok();
    }
}
